from instance.app_instance import app

import flask
from flask import Flask
from flask import request
from flask import session
from flask import current_app
from flask_login import login_user, logout_user
from flask_principal import Identity, identity_changed

from models.user_model import UserModel

import json

assert isinstance(app, Flask)

@app.login_namager.user_loader
def load_user(user_id):
    return UserModel.query.filter_by(id=int(user_id)).first()

@app.login_manager.request_loader
def load_user_from_request(request):
    # first, try to login using the api_key url arg
    user_id = None
    token = request.args.get('token')

    if not token:
        #next, try to login using Basic Auth
        auth_val = request.headers.get('Authorization')
        if auth_val:
            auth_key = auth_val.replace('Basic ', '', 1)
            try:
                token = base64.b64decode(auth_key)
            except TypeError:
                pass

    sess = None
    if token:
        from werkzeug.datastructures import ImmutableTypeConversionDict
        cookies = request.cookies.copy()
        cookies[app.session_cookie_name] = token
        request.cookies = ImmutableTypeConversionDict(cookies)
        sess = app.session_interface.open_session(app, request)

    if sess and 'user_id' in sess:
        user_id = sess['user_id']

    if user_id:
        user = UserModel.query.filter_by(id=int(user_id)).first()
        return user

    # finally, return None if both methods did not login the user
    return None

@app.route('/api/v1/login', methods=['POST'])
@app.record("login", 'login the system')
def login_api():
    if len(request.data) > 0:
        param = json.loads(request.data)
        if 'username' in param and 'passwd' in param:
            user = UserModel.query.filter_by(username=param['username']).first()
            if user is not None and user.passwd == param['passwd']:
                login_user(user)

                identity_changed.send(current_app._get_current_object(), identity=Identity(user.id))

                callback = flask.request.args.get('callback')
                return '{"token": "%s", "callback": "%s"}' % (session.sid, callback or '')

    return flask.redirect('error.error_404')

@app.route('/api/v1/logout', methods=['GET', 'POST'])
@app.record("logout", 'logout the system')
def logout_api():
    logout_user()
    return '{"result": "logout succeed"}', 200
